home *** CD-ROM | disk | FTP | other *** search
- #include "s_var.h"
-
- inline long abs(long x)
- {
- return x<0 ? -x+1 : x;
- }
- ////////////////////
- Var_Table::Var_Table()
- {
- if((memory = new char[MEMORY_STEP]) == NULL)
- {
- kh_error_code = KH_MEMORY_ERROR;
- memory = NULL;
- adresses = NULL;
- types = NULL;
- return;
- }
- if((adresses = new long[ADRESS_STEP]) == NULL)
- {
- kh_error_code = KH_MEMORY_ERROR;
- delete memory;
- memory = NULL;
- adresses = NULL;
- types = NULL;
- return;
- }
- if((types = new int[ADRESS_STEP]) == NULL)
- {
- kh_error_code = KH_MEMORY_ERROR;
- delete memory;
- delete adresses;
- memory = NULL;
- adresses = NULL;
- types = NULL;
- return;
- }
- memory_size = MEMORY_STEP;
- memory_used = 0;
- size = ADRESS_STEP;
- used = 0;
- marked = 0;
- mem_marked = 0;
-
- memset(memory, 0, memory_size);
- memset(types, FREE, size);
- memset(adresses, 0, P * size); // sizeof POINTER in LARGE model == 4 BYTES
- }
- /////////////////////////////////
- Var_Table::~Var_Table()
- {
- for(; used > 0; used--)
- {
- delete remove(used - 1, OFF);
- }
- delete memory;
- delete adresses;
- delete types;
- }
- /////////////////////////////////
- int Var_Table::get_type(int n)
- {
- int t = types[n];
- if(t >= 0) // Not pointers
- type = size_of = t;
- else if(t < -USER_TYPE) // Array in memory
- { type = t; size_of = -(t + USER_TYPE); }
- else
- { type = P; size_of = t; } // Array in heap
- if(adresses[n] < 0)
- type = FREE;
- return type;
- }
- //////////////////////////////////
- int Var_Table::get_size(int n)
- {
- int t = types[n];
- if(t >= 0) // Not pointers
- return t;
- else if(t < -USER_TYPE) // Array in memory
- return n == used - 1 ? memory_used - abs(adresses[n])
- : abs(adresses[n + 1]) - abs(adresses[n]);
- else
- return P; // Array in heap
- }
- //////////////////////////////////
- void* Var_Table::remove(int n, bool check)
- {
- if(adresses[n] < 0 || n >= used )
- return NULL;
-
- mem_marked += get_size(n);
- void* ret = NULL;
- if(types[n] > -USER_TYPE && types[n] < 0) // Pointer to heap
- (long*)ret = (long*)(((long*)(memory + adresses[n]))[0]);
- marked++;
- adresses[n] = -adresses[n] - 1;
-
- if(check)
- check_memory_compress();
-
- return ret;
- }
- /////////////////////////////////
- long Var_Table::find(int n)
- {
- get_type(n);
- return adresses[n];
- }
- /////////////////////////////////
- int Var_Table::add(void* v, int t, int n, uint elems)
- {
- long addr; // Address of location in memory
- int back = t; // Size of type or array
- if(t < -USER_TYPE)
- back = -(t + USER_TYPE) * elems;
- else if(t < 0)
- back = P;
- if(types[n] != t || n == -1 // Incomp. types or add to the end
- || n == used // Direct write to the end
- || (t < -USER_TYPE && elems > get_size(n))) // Array
- {
- n = used++;
- addr = memory_used;
- memory_used += back;
- if(!check_memory_expand()) // Not enought memory
- {
- used--;
- memory_used -= back;
- return -1;
- }
- }
- else
- addr = adresses[n]; // Insert, not add
-
- switch(t)
- {
- case C: memory[addr] = ((char*)v)[0]; break; // char
- case I: ((int*)(memory + addr))[0] = ((int*)v)[0]; break; // int
- case L: ((long*)(memory + addr))[0] = ((long*)v)[0]; break; // long
- case D: ((double*)(memory + addr))[0] = ((double*)v)[0]; break; // double
- case PC: case PI: case PL: case PD: // Array in memory
- memcpy(memory + addr, (char*)v, back);
- break;
- default:
- ((long*)(memory + addr))[0] = (long)(v);
- break;
- }
- adresses[n] = addr; types[n] = t;
-
- if(n != used - 1 && // Array copied over prev. array and free space find
- (t < -USER_TYPE && elems > abs(adresses[n + 1]) - abs(adresses[n])))
- {
- types[used] = t; // Mark-to-remove
- adresses[used++] = (long)(memory + addr + back);
- }
- return n;
- }
- /////////////////////////////////
- int Var_Table::check_memory_expand()
- {
- int* t = types;
- long* l = adresses;
- char* c = memory;
- if(size <= used)
- {
- if((types = (int*)realloc((int*)types,
- (size = (used / ADRESS_STEP + 1) * ADRESS_STEP) * sizeof(int)))
- == NULL)
- {
- size -= ADRESS_STEP;
- types = t;
- return 0;
- }
- if((adresses = (long*)realloc((long*)adresses,
- size * sizeof(long))) == NULL)
- {
- delete types;
- types = t;
- adresses = l;
- return 0;
- }
- }
- if(memory_size <= memory_used)
- {
- if((memory = (char*)realloc((char*)memory,
- (memory_size = (memory_used / MEMORY_STEP + 1) * MEMORY_STEP)
- * sizeof(char))) == NULL)
- {
- memory = c;
- return 0;
- }
- }
- return 1;
- }
- /////////////////////////////
- int Var_Table::check_memory_compress()
- {
- // if(used / 2 < marked || memory_used / 2 < mem_marked
- // || used == size || memory_used == memory_size)
- return memory_compress();
- // return 0;
- }
- /////////////////////////////
- int Var_Table::memory_compress()
- {
- int removed = 0;
- long shift = 0;
- long addr;
- for(int i = 0; i < used; i++)
- {
- if((addr = adresses[i + removed]) < 0)
- addr = -addr - 1;
- addr -= shift;
- while(adresses[i + removed] < 0 && i + removed < used)
- {
- shift += get_size(i + removed);
- removed++;
- }
- if(i + removed == used)
- break;
-
- int sz = get_size(i + removed);
- memmove(memory + addr, memory + addr + shift, sz);
- int sign = adresses[i + removed] < 0 ? -1 : 1;
- adresses[i] = sign * (abs(adresses[i + removed]) - shift);
- types[i] = types[i + removed];
- }
-
- memory_used -= shift;
- used -= removed;
-
- if(size - used > ADRESS_STEP)
- {
- size = (size / used + 1) * ADRESS_STEP;
- adresses = (long*)realloc((long*)adresses, size * sizeof(long));
- types = (int*)realloc((int*)types, size * sizeof(int));
- }
- marked = 0;
- mem_marked = 0;
- return removed;
- }
- /////////////////////////////////// Demo code ///////////////////////////////
- #include <iostream.h>
- class Demo : public Var_Table
- {
- public:
- void report();
- };
-
- void Demo::report()
- {
- cout << "\r\n";
- for(int i = 0; i < used; i++)
- {
- int type = types[i];
- cout << "i: " << i << ", type: ";
- switch(type)
- {
- case C: cout << "C"; break;
- case I: cout << "I"; break;
- case L: cout << "L"; break;
- case D: cout << "D"; break;
- case PC: cout << "PC"; break;
- case PI: cout << "PI"; break;
- case PL: cout << "PL"; break;
- case PD: cout << "PD"; break;
- default: cout << "pointer"; break;
- }
-
- int sz = type > 0 ? type : (type < -USER_TYPE ? -type : P);
- cout << ", (elem.) size: " << sz << ", value: ";
-
- if(adresses[i] < 0)
- cout << "FREE";
- else
- switch(type)
- {
- case C: cout << ((char*)(memory + adresses[i]))[0]; break;
- case I: cout << ((int*)(memory + adresses[i]))[0]; break;
- case L: cout << ((long*)(memory + adresses[i]))[0]; break;
- case D: cout << ((double*)(memory + adresses[i]))[0]; break;
- case PC: cout << memory + adresses[i]; break;
- default: cout << "POINTER"; break;
- }
- cout << "\r\n";
- }
- cout << "---------------------------------------------\r\n";
- cout << "used: " << used << ", mem. used: " << memory_used << "\r\n";
- }
-
- void main()
- {
- Demo* v = new Demo();
- char c = 'Y';
-
- int i = 3;
- long l = 12;
- double d = 2.5;
- char* s = strdup("Hello"); // Never use stack strings
- char* pc = "KNOW-HOW.SLANG 5.0";
- // int* pi = &i; // ERROR! Destructor will call "delete" for i
-
- // >>>>>>>>> add() check code and alloc/realloc of memory <<<<<<<<<<<<<<<
- v->add(&c, C); // char
- v->add(s, -C); // char* in heap
- v->add(&i, I); // int
- v->add(&l, L); // long
- v->add(&d, D); // double
- v->add(pc, PC, -1, strlen(pc) + 1); // Array in memory
- v->report();
- // >>>>>>>>> remove() check code and alloc/realloc of memory <<<<<<<<<<<<<<<
- delete v->remove(0, OFF); // char, no compress
- v->report();
- delete v->remove(5, OFF);
- v->report();
- delete v->remove(1,OFF); // pointer, compress
- v->report();
- v->memory_compress();
- v->report();
- delete v->remove(2); // int, compress
- v->report();
- delete v->remove(1); // long, compress
- v->report();
-
- delete v;
- }
- //////////////////////////// End of Demo code ///////////////////////////////
-